#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <vector>

const int N = 200005, M = 200005, V = 1000005;
int n, m, cnt, ccid, maxv, q, a[N], dfn[N], low[N], tot[V], odd[V], even[V], ans[N],
    son[N], siz[N];
std::stack<int> stk;

struct Pair {
  int x, y;
  Pair(int x, int y) : x(x), y(y) {}
  inline bool operator<(const Pair &rhs) const {
    return x == rhs.x ? y < rhs.y : x < rhs.x;
  }
};

struct Query {
  bool typ;
  int y, id;
  Query(const bool &typ, const int &y, const int &id) : typ(typ), y(y), id(id) {}
};

std::vector<Query> Q[N];

inline int lowbit(int x) { return x & (-x); }

inline void modify(int x, int v, int *const val) {
  while (x <= maxv) val[x] += v, x += lowbit(x);
}

inline int query(int x, const int *const val) {
  int res = 0;
  while (x) res += val[x], x -= lowbit(x);
  return res;
}

struct Graph {
  struct Edge {
    int v, nxt;
  };
  Edge e[M << 1];
  int e_cnt, heads[N];
  virtual inline void add(const int &u, const int &v) {
    e[++e_cnt].v = v, e[e_cnt].nxt = heads[u], heads[u] = e_cnt;
    e[++e_cnt].v = u, e[e_cnt].nxt = heads[v], heads[v] = e_cnt;
  }
} E, G;

struct DGraph : Graph {
  inline void add(const int &u, const int &v) override {
    e[++e_cnt].v = v, e[e_cnt].nxt = heads[u], heads[u] = e_cnt;
    e[++e_cnt].v = u, e[e_cnt].nxt = heads[v], heads[v] = e_cnt;
    printf("%d %d\n", u, v);
  }
};

void tarjan(int u) {
  dfn[u] = low[u] = ++cnt;
  stk.push(u);
  for (int i = E.heads[u], v; i; i = E.e[i].nxt) {
    if (!dfn[v = E.e[i].v]) {
      tarjan(v);
      low[u] = std::min(low[u], low[v]);
      if (low[v] == dfn[u]) {
        ++ccid;
        for (int tmp = 0; tmp != v;) {
          tmp = stk.top();
          stk.pop();
          G.add(ccid, tmp);
        }
        G.add(ccid, u);
      }
    } else
      low[u] = std::min(low[u], dfn[v]);
  }
}

inline void add(const int &x) {
  ++tot[x];
  if (tot[x] == 1) modify(x, 1, odd);
  else if (tot[x] & 1)
    modify(x, -1, even), modify(x, 1, odd);
  else
    modify(x, -1, odd), modify(x, 1, even);
}

inline void del(const int &x) {
  --tot[x];
  if (tot[x] == 0) modify(x, -1, odd);
  else if (tot[x] & 1)
    modify(x, -1, even), modify(x, 1, odd);
  else
    modify(x, -1, odd), modify(x, 1, even);
}

void pre(int u, int fa) {
  siz[u] = 1;
  for (int i = G.heads[u], v; i; i = G.e[i].nxt) {
    if ((v = G.e[i].v) != fa) {
      pre(v, u);
      siz[u] += siz[v];
      if (siz[v] > siz[son[u]]) son[u] = v;
    }
  }
}

void traverse(int x, int fa, const bool &typ) {
  if (a[x]) typ ? add(a[x]) : del(a[x]);
  for (int i = G.heads[x], v; i; i = G.e[i].nxt)
    if ((v = G.e[i].v) != fa) traverse(v, x, typ);
}

void solve(int x, int fa, bool lit) {
  for (int i = G.heads[x], v; i; i = G.e[i].nxt)
    if ((v = G.e[i].v) != fa && v != son[x]) solve(v, x, false);
  if (son[x]) solve(son[x], x, true);
  if (a[x]) add(a[x]);
  for (int i = G.heads[x], v; i; i = G.e[i].nxt)
    if ((v = G.e[i].v) != fa && v != son[x]) traverse(v, x, true);

  for (auto &i : Q[x]) ans[i.id] = query(i.y, i.typ ? odd : even);

  if (!lit) traverse(x, fa, false);
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("testdata.in", "r", stdin);
  freopen("testdata.out", "w", stdout);
#else
  freopen("P3180 [HAOI2016]地图.in", "r", stdin);
  freopen("P3180 [HAOI2016]地图.out", "w", stdout);
#endif
#endif

  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), maxv = std::max(maxv, a[i]);
  for (int i = 1, x, y; i <= m; ++i) {
    scanf("%d%d", &x, &y);
    E.add(x, y);
  }
  ccid = n;
  tarjan(1);
  scanf("%d", &q);
  for (int i = 1, typ, x, y; i <= q; ++i) {
    scanf("%d%d%d", &typ, &x, &y);
    maxv = std::max(maxv, y);
    Q[x].emplace_back(typ, y, i);
  }
  pre(1, 0);
  solve(1, 0, true);
  for (register int *i = ans + 1, *end = ans + q + 1; i != end; ++i) printf("%d\n", *i);
  return 0;
}
